home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / svgancui.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  12KB  |  579 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * ncurses frontend for a text-based user interface.
  5.   *
  6.   * Copyright 1996 Bernd Schmidt
  7.   * If you find the routines in this file useful, you may use them in your
  8.   * programs without restrictions. Essentially, it's in the public domain.
  9.   *
  10.   */
  11.  
  12.  
  13. #include "sysconfig.h"
  14. #include "sysdeps.h"
  15.  
  16. #ifdef HAVE_NCURSES_H
  17. #include <ncurses.h>
  18. #else
  19. #include <curses.h>
  20. #endif
  21. #include <ctype.h>
  22.  
  23. #include "config.h"
  24. #include "options.h"
  25. #include "uae.h"
  26. #include "tui.h"
  27.  
  28. #ifdef DONT_HAVE_ATTR_T
  29. typedef int attr_t;
  30. #endif
  31.  
  32. static WINDOW *currwin;
  33.  
  34. static WINDOW *winstack[10]; /* more than enough */
  35. static int winnr = 0;
  36.  
  37. void tui_setup(void)
  38. {
  39.     int i;
  40.  
  41.     for (i = 0; i < 10; i++)
  42.     winstack[i] = NULL;
  43.     /* From the ncurses manpage... */
  44.     initscr(); start_color(); cbreak(); noecho(); nonl(); intrflush(stdscr, FALSE); keypad(stdscr, TRUE);
  45.     currwin = stdscr;
  46.     if (has_colors()) {
  47.     init_pair(1, COLOR_WHITE, COLOR_BLUE);
  48.     init_pair(2, COLOR_BLACK, COLOR_WHITE);
  49.     wattron(currwin, COLOR_PAIR(1) | A_BOLD);
  50.     wbkgd(currwin, ' '|COLOR_PAIR(1));
  51.     }
  52.  
  53.     winstack[0] = stdscr;
  54.     winnr = 1;
  55. }
  56.  
  57. int tui_lines(void)
  58. {
  59.     return LINES;
  60. }
  61.  
  62. int tui_cols(void)
  63. {
  64.     return COLS;
  65. }
  66.  
  67. void tui_shutdown(void)
  68. {
  69.     endwin();
  70. }
  71.  
  72. void tui_refresh(void)
  73. {
  74.     int w;
  75.     for (w = 0; w < winnr; w++) {
  76.     touchwin(winstack[w]);
  77.     wnoutrefresh(winstack[w]);
  78.     }
  79.     doupdate();
  80. }
  81.  
  82. void tui_puts(const char *s)
  83. {
  84.     waddstr(currwin, s);
  85. }
  86.  
  87. void tui_cursoff(void)
  88. {
  89. }
  90.  
  91. void tui_curson(void)
  92. {
  93. }
  94.  
  95. void tui_putc(char c)
  96. {
  97.     waddch(currwin, c);
  98. }
  99.  
  100. void tui_cr(void)
  101. {
  102.     waddch(currwin, '\r');
  103. }
  104.  
  105. char tui_getc(void)
  106. {
  107.     return getch();
  108. }
  109.  
  110. void tui_gotoxy(int x, int y)
  111. {
  112.     x--; y--;
  113.     wmove(currwin, y, x);
  114. }
  115.  
  116. void tui_selwin(int w)
  117. {
  118.     currwin = winstack[w];
  119. }
  120.  
  121. void tui_clrwin(int w)
  122. {
  123.     werase(winstack[w]);
  124. }
  125.  
  126. void tui_drawbox(int w)
  127. {
  128.     wborder(winstack[w], 0, 0, 0, 0, 0, 0, 0, 0);
  129. }
  130.  
  131. void tui_hline(int x1, int y1, int x2)
  132. {
  133.     wmove(currwin, y1-1, x1-1);
  134.     whline(currwin, 0, x2-x1+1);
  135. }
  136.  
  137. int tui_dlog(int x1, int y1, int x2, int y2)
  138. {
  139.     x1--; y1--;
  140.     winstack[winnr] = newwin(y2 - y1, x2 - x1, y1, x1);
  141.     return winnr++;
  142. }
  143.  
  144. void tui_dlogdie(int w)
  145. {
  146.     if (currwin == winstack[w])
  147.     currwin = stdscr;
  148.     delwin(winstack[w]);
  149.     winstack[w] = NULL;
  150.     while (winstack[winnr-1] == NULL)
  151.     winnr--;
  152.  
  153.     for (w = 0; w < winnr; w++)
  154.     redrawwin(winstack[w]), wrefresh(winstack[w]);
  155. }
  156.  
  157. int tui_gets(char *buf, int x, int y, int n)
  158. {
  159.     int i = 0;
  160.     for (;;) {
  161.     int c, j;
  162.  
  163.     buf[i] = 0;
  164.     wmove(currwin, y, x);
  165.     for (j = 0; j < i; j++)
  166.         waddch(currwin, buf[j]);
  167.     for (; j < n; j++)
  168.         waddch(currwin, ' ');
  169.  
  170.     wmove(currwin, y, x + i);
  171.     wrefresh(currwin);
  172.  
  173.     c = getch();
  174.  
  175.     wmove(currwin, y, x + i);
  176.     if (c == 13)
  177.         return 1;
  178.     else if (c == 27)
  179.         return 0;
  180.     else if (i > 0 && c == KEY_BACKSPACE)
  181.         i--;
  182.     else if (i + 1 < n && !iscntrl(c))
  183.         buf[i++] = c;
  184.     }
  185. }
  186.  
  187. int tui_wgets(char *buf, const char *title, int n)
  188. {
  189.     int l = strlen(title);
  190.     int ww = (l > n ? l : n) + 2;
  191.     int w = tui_dlog((tui_cols()-ww)/2, tui_lines()/2-1, (tui_cols()+ww)/2, tui_lines()/2+1);
  192.     int result;
  193.  
  194.     tui_selwin(w); tui_drawbox(w);
  195.     wmove(currwin, 0, (ww-l)/2);
  196.     waddstr(currwin, title);
  197.     result = tui_gets(buf, 1, 1, n);
  198.     tui_dlogdie(w);
  199.     return result;
  200. }
  201.  
  202. int tui_menubrowse(struct bstring *menu, int xoff, int yoff, int selected, int height)
  203. {
  204.     int count = 0, maxsel = 0, maxw = 0;
  205.     int i, j, w, s, yp, oldyp;
  206.     chtype moresave[6][2];
  207.     int xpos, ypos;
  208.  
  209.     const char *mtitle = NULL;
  210.  
  211.     for (i = 0; menu[i].val != -3; i++) {
  212.     int tmp;
  213.     if (menu[i].val == -4) {
  214.         if (maxsel < selected)
  215.         selected--;
  216.         continue;
  217.     }
  218.     if (menu[i].val != 0) {
  219.         count++;
  220.         if (menu[i].val != -2)
  221.         maxsel++;
  222.     } else
  223.         mtitle = menu[i].data;
  224.     if ((tmp = strlen(menu[i].data)) > maxw)
  225.         maxw = tmp;
  226.     }
  227.     if (height > count)
  228.     height = count;
  229.     maxw += 3;
  230.     if (strlen(mtitle ? mtitle : "") + 8 > maxw)
  231.     maxw = strlen(mtitle ? mtitle : "") + 8;
  232.     if (xoff > 0)
  233.     xpos = xoff;
  234.     else
  235.     xpos = tui_cols() + xoff - maxw - 1;
  236.     if (yoff > 0)
  237.     ypos = yoff;
  238.     else
  239.     ypos = tui_lines() + yoff - height - 2;
  240.     w = tui_dlog(xpos, ypos, xpos+maxw, ypos+height+1);
  241.     tui_selwin(w);
  242.     tui_drawbox(w);
  243.     if (mtitle != NULL) {
  244.     mvwaddstr(currwin, 0, 1, mtitle);
  245.     }
  246.     for (i = 0; i < 6; i++) {
  247.     moresave[i][0] = mvwinch(currwin, 0, maxw-6+i);
  248.     moresave[i][1] = mvwinch(currwin, height+1, maxw-6+i);
  249.     }
  250.     s = yp = 0; oldyp = -1;
  251.     for (;;) {
  252.     int c;
  253.     int s2;
  254.  
  255.     while (selected < yp)
  256.         yp--;
  257.     while (selected >= yp + height)
  258.         yp++;
  259.     if (yp == 0)
  260.         for (i = 0; i < 6; i++)
  261.         mvwaddch(currwin, 0, maxw-6+i, moresave[i][0]);
  262.     else
  263.         mvwaddstr(currwin, 0, maxw-6, "(more)");
  264.     if (yp + height == count)
  265.         for (i = 0; i < 6; i++)
  266.         mvwaddch(currwin, height+1, maxw-6+i, moresave[i][1]);
  267.     else
  268.         mvwaddstr(currwin, height+1, maxw-6, "(more)");
  269.     for (i = s2 = j = 0; i < count; i++, j++) {
  270.         int k, x;
  271.         attr_t a = s2 == selected ? A_STANDOUT : 0;
  272.         while (menu[j].val == 0 || menu[j].val == -4)
  273.         j++;
  274.         if (i >= yp && i < yp+height) {
  275.         mvwaddch(currwin, 1+i-yp, 1, ' ' | a);
  276.         for (k = x = 0; menu[j].data[k]; k++, x++) {
  277.             int a2 = 0;
  278.             c = menu[j].data[k];
  279.             if (c == '_')
  280.             c = menu[j].data[++k], a2 = A_UNDERLINE;
  281.             mvwaddch(currwin, 1+i-yp, 2+x, c | a | a2);
  282.         }
  283.         for (; x < maxw-2; x++) {
  284.             mvwaddch(currwin, 1+i-yp, 2+x, ' ' | a);
  285.         }
  286.         }
  287.         if (menu[j].val != -2)
  288.         s2++;
  289.     }
  290.  
  291.     tui_refresh();
  292.     c = getch();
  293.     if (c == 27) {
  294.         tui_dlogdie(w);
  295.         return -1;
  296.     } else if (c == KEY_ENTER || c == 13 || c == ' ') {
  297.         tui_dlogdie(w);
  298.         for (i = s2 = j = 0; s2 <= selected; j++) {
  299.         if (menu[j].val == -4) {
  300.             i++; j++; continue;
  301.         }
  302.         while (menu[j].val == 0)
  303.             j++;
  304.         if (s2 == selected)
  305.             return i;
  306.         if (menu[j].val != -2)
  307.             s2++, i++;
  308.         }
  309.         abort();
  310.     } else switch (c) {
  311.      case KEY_UP:
  312.         if (selected > 0)
  313.         selected--;
  314.         break;
  315.      case KEY_DOWN:
  316.         if (selected + 1 < count)
  317.         selected++;
  318.         break;
  319.      case KEY_PPAGE:
  320.         if (selected > height)
  321.         selected -= height;
  322.         else
  323.         selected = 0;
  324.         break;
  325.      case KEY_NPAGE:
  326.         if (selected + height < count)
  327.         selected += height;
  328.         else
  329.         selected = count-1;
  330.         break;
  331.      default:
  332.         for (j = i = 0; menu[i].val != -3; i++)
  333.         if (menu[i].val == toupper(c)) {
  334.             tui_dlogdie(w);
  335.             return j;
  336.         } else if (menu[i].val == -1 || menu[i].val == -4 || menu[i].val > 0) {
  337.             j++;
  338.         }
  339.  
  340.         break;
  341.     }
  342.     }
  343.     return -1; /* Can't get here */
  344. }
  345.  
  346. void tui_errorbox(const char *err)
  347. {
  348.     const char *hak = "Hit any key";
  349.     int n = strlen(hak);
  350.     int l = strlen(err);
  351.     int ww = (l > n ? l : n) + 2;
  352.     int w = tui_dlog((tui_cols()-ww)/2, tui_lines()/2-1, (tui_cols()+ww)/2, tui_lines()/2+1);
  353.     tui_selwin(w); tui_drawbox(w);
  354.  
  355.     wmove(currwin, 0, (ww-6)/2);
  356.     waddstr(currwin, "Error!");
  357.     wmove(currwin, 1, (ww-l)/2);
  358.     waddstr(currwin, err);
  359.     wmove(currwin, 2, (ww-n)/2);
  360.     waddstr(currwin, hak);
  361.  
  362.     wrefresh(currwin);
  363.     for (;;) {
  364.     int c = getch();
  365.     if (c == 13)
  366.         break;
  367.     }
  368.     tui_dlogdie(w);
  369. }
  370.  
  371. static char *pattern;
  372. static int maxlen;
  373.  
  374. static void put_filename(char *s, int x, int y, attr_t a)
  375. {
  376.     char buf[256];
  377.     int i;
  378.  
  379.     tui_gotoxy(x,y);
  380.     if (strcmp(s, ".") == 0)
  381.     strcpy(buf, "(none)");
  382.     else
  383.     strcpy(buf, s);
  384.     buf[maxlen] = 0;
  385.     for (i = 0; i < strlen(buf); i++)
  386.     waddch(currwin, buf[i] | a);
  387.     for (; i < maxlen; i++)
  388.     waddch(currwin, ' ' | a);
  389. }
  390.  
  391. static char fsbuf[256];
  392.  
  393. static int selectfn(const struct dirent *de)
  394. {
  395.     int l1, l2;
  396.  
  397. /*    l1 = strlen(pattern + 1);*/
  398.     l2 = strlen(de->d_name);
  399.  
  400.     if (l2 >= tui_cols()-10) /* Restrict length of filenames so we won't mess up the display */
  401.     return 0;
  402.  
  403.     /* No pattern matching for now. But we don't show hidden files. */
  404.     if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0
  405.     && de->d_name[0] == '.')
  406.     return 0;
  407.     if (l2 > maxlen)
  408.     maxlen = l2;
  409.     return 1;
  410. }
  411.  
  412. static int my_alphasort (const void *a, const void *b)
  413. {
  414.     return strcmp ((*(struct dirent **) a)->d_name,
  415.            (*(struct dirent **) b)->d_name);
  416. }
  417.  
  418. char *tui_filereq(char *s, char *oldfile, const char *title)
  419. {
  420.     char cwd[256];
  421.     char *retval = fsbuf;
  422.     char *tmp;
  423.     int fin = 0;
  424.     chtype moresave[6][2];
  425.  
  426.     /* Save wd */
  427.     if (getcwd(cwd, 256) == NULL)
  428.     return NULL;
  429.  
  430.     /* Change into directory of old file */
  431.     strcpy(fsbuf, oldfile);
  432.     tmp = strrchr(fsbuf, '/');
  433.     if (tmp != NULL) {
  434.     *tmp = 0;
  435.     if (strlen(fsbuf) > 0)
  436.         chdir(fsbuf);
  437.     }
  438.  
  439.     pattern = s;
  440.     if (s[0] != '*')
  441.     fprintf(stderr, "Can't handle wildcard %s\n", s);
  442.     if (s[1] != 0 && strchr(s+1, '*') != NULL)
  443.     fprintf(stderr, "Can't handle wildcard %s\n", s);
  444.     for (;!fin;) {
  445.     struct dirent **names;
  446.     int i, w, n, l, yp, oldyp, s;
  447.  
  448.     maxlen = 0;
  449.     n = scandir(".", &names, selectfn, my_alphasort);
  450.  
  451.     if (n <= 0)
  452.         return NULL;
  453.     if (title != NULL && strlen(title) + 6 > maxlen)
  454.         maxlen = strlen(title) + 6;
  455.     l = n;
  456.     if (l > 15)
  457.         l = 15;
  458.     yp = s = 0; oldyp = -1;
  459.     w = tui_dlog(tui_cols() - maxlen - 8, 5, tui_cols() - 5, 5 + l + 1);
  460.     tui_selwin(w); tui_drawbox(w);
  461.     if (title)
  462.         mvwaddstr(currwin, 0, 2, title);
  463.     for (i = 0; i < 6; i++) {
  464.         moresave[i][0] = mvwinch(currwin, 0, maxlen-3+i);
  465.         moresave[i][1] = mvwinch(currwin, l+1, maxlen-3+i);
  466.     }
  467.     for (;;) {
  468.         int c;
  469.         char tmp[256];
  470.         while (s < yp)
  471.         yp--;
  472.         while (s >= yp + l)
  473.         yp++;
  474.         if (oldyp != yp) {
  475.         oldyp = yp;
  476.         for (i = 0; i < l; i++) {
  477.             put_filename(names[i + yp]->d_name, 3, 2 + i, 0);
  478.         }
  479.         }
  480.         put_filename(names[s]->d_name, 3, 2 + s - yp, A_STANDOUT);
  481.  
  482.         if (yp == 0)
  483.         for (i = 0; i < 6; i++)
  484.             mvwaddch(currwin, 0, maxlen-3+i, moresave[i][0]);
  485.         else
  486.         mvwaddstr(currwin, 0, maxlen-3, "(more)");
  487.         if (yp + l == n)
  488.         for (i = 0; i < 6; i++)
  489.             mvwaddch(currwin, l+1, maxlen-3+i, moresave[i][1]);
  490.         else
  491.         mvwaddstr(currwin, l+1, maxlen-3, "(more)");
  492.  
  493.         tui_refresh();
  494.         c = getch();
  495.         put_filename(names[s]->d_name, 3, 2 + s - yp, 0);
  496.         if (c == 27) {
  497.         retval = NULL; fin = 1;
  498.         break;
  499.         } else if (c == KEY_ENTER || c == 13 || c == ' ') {
  500.         int err;
  501.  
  502.         if (strcmp(names[s]->d_name, ".") == 0) {
  503.             fin = 1;
  504.             strcpy(fsbuf, "");
  505.             break;
  506.         }
  507.         err = chdir(names[s]->d_name);
  508.  
  509.         if (err == 0)
  510.             break;
  511.         else if (errno == ENOTDIR) {
  512.             fin = 1;
  513.             if (getcwd(fsbuf, 256) == NULL)
  514.             retval = NULL;
  515.             if (strlen(fsbuf) + strlen(names[s]->d_name) + 2 >= 256)
  516.             retval = NULL;
  517.             else {
  518.             strcat(fsbuf, "/");
  519.             strcat(fsbuf, names[s]->d_name);
  520.             }
  521.             break;
  522.         } /* else what? */
  523.         }
  524.         switch (c) {
  525.          case KEY_UP:
  526.         if (s > 0)
  527.             s--;
  528.         break;
  529.          case KEY_DOWN:
  530.         if (s + 1 < n)
  531.             s++;
  532.         break;
  533.          case KEY_PPAGE:
  534.         if (s > l)
  535.             s -= l;
  536.         else
  537.             s = 0;
  538.         break;
  539.          case KEY_NPAGE:
  540.         if (s + l < n)
  541.             s += l;
  542.         else
  543.             s = n - 1;
  544.         break;
  545.          default:
  546.         i = 0;
  547.         if (names[s]->d_name[0] == c)
  548.             i = s+1;
  549.         for (; i < n*2; i++) {
  550.             int j = i;
  551.             if (i >= n)
  552.             j -= n;
  553.             if (names[j]->d_name[0] == c) {
  554.             s = j;
  555.             break;
  556.             }
  557.         }
  558.         }
  559.     }
  560. #if 0
  561.     /* @@@ is this right? */
  562.     for (i = 0; i < n; i++)
  563.         free(names[i]);
  564.     free(names);
  565. #endif
  566.     tui_dlogdie(w);
  567.     }
  568.     chdir(cwd);
  569.     return retval;
  570. }
  571.  
  572. int tui_backup_optionsfile(void)
  573. {
  574.     char tmp[257];
  575.     strcpy(tmp, optionsfile);
  576.     strcat(tmp, "~");
  577.     return rename(optionsfile, tmp);
  578. }
  579.